package com.example.codegenerator.util;

import org.apache.maven.plugin.logging.Log;

import java.io.File;
import java.util.List;
import java.util.Map;

public class ModuleStringWriterUtils {

    /**
     * 生成目录
     * @param path 文件模块路径
     * @param log 日志
     */
    public static void mkdir(String path, Log log) {
        if(!path.contains("/")) {
            log.error("目录格式不正确，路径必须包含分隔符'/'");
            return;
        }
        String basePath = path.substring(0, path.lastIndexOf("/"));
        File fileCommon = new File(basePath + "/common");
        if(!fileCommon.exists()) {
            log.info("生成文件" + basePath + "/common 成功标识：" + fileCommon.mkdir());
        }
        File fileBase = new File(basePath + "/common/base");
        if(!fileBase.exists()) {
            log.info("生成文件" + basePath + "/common/base 成功标识：" + fileBase.mkdir());
        }

        File file = new File(path);
        if(!file.exists()){
            log.info("生成文件" + path + "成功标识：" + file.mkdir());
        }
        File file1 = new File(path + "/vo");
        if(!file1.exists()){
            log.info("生成文件" + path + "/vo成功标识：" + file1.mkdir());
        }
        File file2 = new File(path + "/dao");
        if(!file2.exists()){
            log.info("生成文件" + path + "/dao成功标识：" + file2.mkdir());
        }
        File file3 = new File(path + "/dao/entity");
        if(!file3.exists()){
            log.info("生成文件" + path + "/dao/entity成功标识：" + file3.mkdir());
        }
        File file4 = new File(path + "/service");
        if(!file4.exists()){
            log.info("生成文件" + path + "/service成功标识：" + file4.mkdir());
        }
        File file5 = new File(path + "/service/impl");
        if(!file5.exists()){
            log.info("生成文件" + path + "/service/impl成功标识：" + file5.mkdir());
        }
        File file6 = new File(path + "/controller");
        if(!file6.exists()){
            log.info("生成文件" + path + "/controller成功标识：" + file6.mkdir());
        }
    }

    /**
     * 生成common模块文件
     * @param path 生成模块时顺带生成common目录下的文件
     */
    public static void generateCommonFiles(String path) {
        String basePath = path.substring(0, path.lastIndexOf("/"));
        String corePackage = StringUtils.getBasePackage(basePath);
        File file = new File(basePath + "/common/base/Pojo.java");
        if (!file.exists()) {
            String pojoContent = "package " + corePackage + ".common.base;\n\n" +
                    "import com.alibaba.fastjson.JSONObject;\n\n" +
                    "public class Pojo {\n" +
                    "    @Override\n" +
                    "    public String toString() {\n" +
                    "        return JSONObject.toJSONString(this,  true);\n" +
                    "    }\n" +
                    "}";
            FileUtils.writeContentToFile(file, pojoContent);
        }
        File file1 = new File(basePath + "/common/base/BaseResponse.java");
        if (!file1.exists()) {
            String responseContext = "package " + corePackage + ".common.base;\n\n" +
                    "public class BaseResponse<T> extends Pojo {\n" +
                    "    private int code;\n" +
                    "    private String msg;\n" +
                    "    private T data;\n\n" +
                    "    public void ok(T data){\n" +
                    "        this.code = 0;\n" +
                    "        this.msg = \"success\";\n" +
                    "        this.data = data;\n" +
                    "    }\n\n" +
                    "    public void ok(){\n" +
                    "        this.code = 0;\n" +
                    "        this.msg = \"success\";\n" +
                    "    }\n\n" +
                    "    public void errMsg(String msg) {\n" +
                    "        this.code = -1;\n" +
                    "        this.msg = msg;\n" +
                    "    }\n\n" +
                    "    public int getCode() {\n" +
                    "        return code;\n" +
                    "    }\n\n" +
                    "    public void setCode(int code) {\n" +
                    "        this.code = code;\n" +
                    "    }\n\n" +
                    "    public String getMsg() {\n" +
                    "        return msg;\n" +
                    "    }\n\n" +
                    "    public void setMsg(String msg) {\n" +
                    "        this.msg = msg;\n" +
                    "    }\n\n" +
                    "    public T getData() {\n" +
                    "        return data;\n" +
                    "    }\n\n" +
                    "    public void setData(T data) {\n" +
                    "        this.data = data;\n" +
                    "    }\n\n" +
                    "}\n";
            FileUtils.writeContentToFile(file1, responseContext);
        }
    }

    /**
     * 生成功能模块文件
     * @param metaDataPath 获取表字段的文本内容，可以是\t或者|隔开的字段信息，后续还可以根据建表语句获取元数据
     * @param path 生成模块时顺带生成common目录下的文件
     * @param tableNames 生成代码对应的表名称，多个用','分割
     * @param swaggerFlag 是否生成springDoc文档的swagger注解
     * @param commonOverwrite 是否覆盖原来的文件内容
     */
    public static void generateModuleFiles(String metaDataPath, String path, String tableNames,
                                           String swaggerFlag, String commonOverwrite) {
        boolean boolOverride = "true".equals(commonOverwrite);
        boolean bool = "true".equals(swaggerFlag);
        String module = path;
        if(path.contains("/")) {
            module = path.replace("/", ".");
        }
        if(path.contains("\\")) {
            module = module.replace("\\", ".");
        }
        module = module.substring(module.indexOf(".java.") + ".java.".length());
        if(module.endsWith(".")) {
            module = module.substring(0, module.length() - 1);
        }
        String corePackage = module.substring(0, module.lastIndexOf("."));
        if (tableNames != null && !tableNames.isEmpty()) {
            String[] tableArr = tableNames.split(",");
            for (String tableName : tableArr) {
                tableName = tableName.trim();
                String table = getTableEngName(tableName);
                String className = StringUtils.getMethodName(StringUtils.getFieldName(table), "");
                String fieldClassName = StringUtils.getFieldName(table);
                String tableNameDesc = tableName.contains("-")?
                        tableName.substring(tableName.indexOf("-") + "-".length()).trim() : className;
                List<Map<String, String>> list = FileUtils.getMetaData(metaDataPath, table);
                List<Map<String, String>> keyList = FileUtils.getIds(metaDataPath, table);
                ParamVO paramVO = new ParamVO();
                paramVO.setPath(path);
                paramVO.setModule(module);
                paramVO.setCorePackage(corePackage);
                paramVO.setTableName(tableName);
                paramVO.setTableEngName(table);
                paramVO.setTableNameDesc(tableNameDesc);
                paramVO.setClassName(className);
                paramVO.setFieldClassName(fieldClassName);
                paramVO.setList(list);
                paramVO.setKeyList(keyList);
                File file1 = new File(path + "/dao/entity/" + className + "Entity.java");
                if (!file1.exists() || boolOverride) {
                    FileUtils.writeContentToFile(file1, getEntity(paramVO));
                }
                File file2 = new File(path + "/vo/" + className + "VO.java");
                if (!file2.exists() || boolOverride) {
                    FileUtils.writeContentToFile(file2, getVO(paramVO, bool));
                }
                File file3 = new File(path + "/dao/" + className + "Dao.java");
                if (!file3.exists() || boolOverride) {
                    FileUtils.writeContentToFile(file3, getDao(paramVO));
                }
                File file4 = new File(path + "/dao/" + className + "Dao.xml");
                if (!file4.exists() || boolOverride) {
                    FileUtils.writeContentToFile(file4, getDaoXml(paramVO));
                }
                File file5 = new File(path + "/service/" + className + "Service.java");
                if (!file5.exists() || boolOverride) {
                    FileUtils.writeContentToFile(file5, getService(paramVO));
                }
                File file6 = new File(path + "/service/impl/" + className + "ServiceImpl.java");
                if (!file6.exists() || boolOverride) {
                    FileUtils.writeContentToFile(file6, getServiceImpl(paramVO));
                }
                File file7 = new File(path + "/controller/" + className + "Controller.java");
                if (!file7.exists() || boolOverride) {
                    FileUtils.writeContentToFile(file7, getController(paramVO, bool));
                }
            }
        }
    }

    /**
     * Entity文件内容
     */
    public static String getEntity(ParamVO paramVO) {
        String fieldInfoStr = getEntityFields(paramVO.getList(), 0, false);
        String module = paramVO.getModule();
        String className = paramVO.getClassName();
        String tableNameDesc = paramVO.getTableNameDesc();
        String string = "package " + module + ".dao.entity;\n\n" +
                (fieldInfoStr.contains("private Timestamp ")? "import java.sql.Timestamp;\n\n":"") +
                (fieldInfoStr.contains("private BigDecimal ")? "import java.sql.BigDecimal;\n\n":"") +
                "/**\n" +
                " * " + tableNameDesc + "\n" +
                "*/\n" +
                "public class " + className + "Entity {\n";
        return string + fieldInfoStr;
    }

    /**
     * Entity 字段
     * @param paramVO paramVO
     * @param bool 是否需要swagger文档
     */
    public static String getVO(ParamVO paramVO, boolean bool) {
        String module = paramVO.getModule();
        String corePackage = paramVO.getCorePackage();
        String className = paramVO.getClassName();
        String tableNameDesc = paramVO.getTableNameDesc();
        String string = "package " + module + ".vo;\n\n" +
                "import " + corePackage + ".common.base.Pojo;\n" +
                (bool?"import io.swagger.v3.oas.annotations.media.Schema;\n\n":"") +
                "/**\n" +
                "* " + tableNameDesc + "\n" +
                "*/\n" +
                (bool?"@Schema(description = \"" + tableNameDesc + "\")\n":"") +
                "public class " + className + "VO extends Pojo {\n";
        return string + getEntityFields(paramVO.getList(), 1, bool);
    }

    /**
     * Entity 字段
     * @param list list
     * @param type entity or VO
     * @param bool 是否需要swagger文档
     */
    public static String getEntityFields(List<Map<String, String>> list, int type, boolean bool) {
        StringBuilder stringBuilder = new StringBuilder();
        for (Map<String, String> map : list) {
            String comment = map.get("column_comment");
            if (type != 0 && bool) {
                stringBuilder.append("    @Schema(description = \"").append(comment).append("\", example = \"\")\n");
            } else {
                stringBuilder.append("    /**\n     *").append(comment).append("\n     */\n");
            }
            String columnName = map.get("column_name");
            String columnType = map.get("column_type");
            String fieldName = StringUtils.getFieldName(columnName);
            String fieldTypeName = StringUtils.getFieldTypeName(columnType);
            if(type == 1) {
                fieldTypeName = "String";
            }
            stringBuilder.append("    private ").append(fieldTypeName).append(" ").append(fieldName).append(";\n\n");
        }

        for (Map<String, String> map : list) {
            String columnName = map.get("column_name");
            String columnType = map.get("column_type");
            String fieldName = StringUtils.getFieldName(columnName);
            String fieldTypeName = StringUtils.getFieldTypeName(columnType);
            if(type == 1) {
                fieldTypeName = "String";
            }
            stringBuilder.append("    public ").append(fieldTypeName).append(StringUtils.getMethodName(fieldName, " get")).append("(){\n" +
                    "        return ").append(fieldName).append(";\n" +
                    "    }\n");
            stringBuilder.append("    public void ").append(StringUtils.getMethodName(fieldName, "set")).append("(").append(fieldTypeName).append(" ").append(fieldName).append("){\n" +
                    "        this.").append(fieldName).append(" = ").append(fieldName).append(";\n" +
                    "    }\n");
        }

        stringBuilder.append("}\n");
        return stringBuilder.toString();
    }

    /**
     * Dao文件内容
     */
    public static String getDao(ParamVO paramVO) {
        String module = paramVO.getModule();
        String className = paramVO.getClassName();
        String fieldClassName = paramVO.getFieldClassName();
        String tableNameDesc = paramVO.getTableNameDesc();
        return "package " + module + ".dao;\n\n" +
                "import com.baomidou.mybatisplus.extension.plugins.pagination.Page;\n" +
                "import " + module + ".vo." + className + "VO;\n" +
                "import " + module + ".dao.entity." + className + "Entity;\n" +
                "import org.apache.ibatis.annotations.Param;\n\n" +
                "import java.util.List;\n" +
                "/**\n" +
                "* " + tableNameDesc + "\n" +
                "*/\n" +
                "public interface " + className + "Dao {\n\n" +
                "    List<" + className + "Entity> findByWhere(Page<?> page, @Param(\"param\") " + className + "VO " + fieldClassName + "VO);\n\n" +
                "    " + className + "Entity findByKey(@Param(\"param\") " + className + "VO " + fieldClassName + "VO);\n\n" +
                "    int insert(@Param(\"param\") " + className + "Entity " + fieldClassName + "Entity);\n\n" +
                "    int updateByKey(@Param(\"param\") " + className + "Entity " + fieldClassName + "Entity);\n\n" +
                "    int deleteByKey(@Param(\"param\") " + className + "VO " + fieldClassName + "VO);\n\n" +
                "}";
    }

    /**
     * DaoXml文件内容
     */
    public static String getDaoXml(ParamVO paramVO) {
        String module = paramVO.getModule();
        String className = paramVO.getClassName();
        String table = paramVO.getTableEngName();
        List<Map<String, String>> list = paramVO.getList();
        List<Map<String, String>> keyList = paramVO.getKeyList();
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
                "<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n" +
                "<mapper namespace=\"").append(module).append(".dao.").append(className).append("Dao\">\n\n");
        stringBuilder.append("    <resultMap id=\"").append(className).append("ResultMap\" type=\"").append(module).append(".dao.entity.").append(className).append("Entity\">\n");
        for (Map<String, String> map : keyList) {
            String columnName = map.get("column_name");
            String fieldName = StringUtils.getFieldName(columnName);
            String columnType = map.get("column_type");
            String jdbcType = StringUtils.getJdbcTypeName(columnType);
            stringBuilder.append("        <id column=\"").append(columnName).append("\" property=\"").append(fieldName).append("\" jdbcType=\"").append(jdbcType).append("\"/>\n");
        }
        for (Map<String, String> map : list) {
            if(keyList.contains(map)) {
                continue;
            }
            String columnName = map.get("column_name");
            String fieldName = StringUtils.getFieldName(columnName);
            String columnType = map.get("column_type");
            String jdbcType = StringUtils.getJdbcTypeName(columnType);
            stringBuilder.append("        <result column=\"").append(columnName).append("\" property=\"").append(fieldName).append("\" jdbcType=\"").append(jdbcType).append("\"/>\n");
        }
        stringBuilder.append("    </resultMap>\n\n");
        stringBuilder.append("    <sql id=\"select_sql_").append(table).append("\">\n" +
                "        select ");
        for (Map<String, String> map : list) {
            String columnName = map.get("column_name");
            stringBuilder.append(columnName);
            stringBuilder.append(",");
        }
        stringBuilder.deleteCharAt(stringBuilder.length() - 1).append(" from ").append(table).append("\n" +
                "    </sql>\n\n");
        stringBuilder.append("    <sql id=\"where_sql_").append(table).append("\">\n" +
                "        <where>\n            <if test=\"param != null\">\n");

        for (Map<String, String> map : list) {
            String columnName = map.get("column_name");
            String columnType = map.get("column_type");
            String jdbcType=", jdbcType=" + StringUtils.getJdbcTypeName(columnType);
            String fieldName = "param." + StringUtils.getFieldName(columnName);
            if (!keyList.contains(map)) {
                stringBuilder.append("                <if test=\"").append(fieldName).append(" !=null and ").append(fieldName).append(" !=''\">\n" +
                        "                    and ").append(columnName).append("=#{").append(fieldName).append(jdbcType).append("}\n" +
                        "                </if>\n");
            }
        }

        stringBuilder.append("            </if>\n        </where>\n" +
                "    </sql>\n\n");
        stringBuilder.append("    <select id=\"findByWhere\" resultMap=\"").append(className).append("ResultMap\">\n" +
                "        <include refid=\"select_sql_").append(table);
        stringBuilder.append("\"/>\n" +
                "        <include refid=\"where_sql_").append(table).append("\"/>\n" +
                "    </select>\n\n");
        String keys;
        StringBuilder stringBuilder1 = new StringBuilder();
        for (Map<String, String> map : keyList) {
            String columnName = map.get("column_name");
            String columnType = map.get("column_type");
            String jdbcType=", jdbcType=" + StringUtils.getJdbcTypeName(columnType);
            String fieldName = "param." + StringUtils.getFieldName(columnName);
            if(stringBuilder1.length() > 0) {
                stringBuilder1.append("        and ");
            }
            stringBuilder1.append(columnName).append("=#{").append(fieldName).append(jdbcType).append("}\n");
        }
        keys = stringBuilder1.toString();
        stringBuilder.append("    <select id=\"findByKey\" resultMap=\"").append(className).append("ResultMap\">\n" +
                "        <include refid=\"select_sql_").append(table).append("\"/>\n" +
                "        where ").append(keys).append("    </select>\n\n");
        stringBuilder.append("    <insert id=\"insert\">\n" +
                "        insert into ").append(table).append("\n        (");

        for (Map<String, String> map : list) {
            String columnName = map.get("column_name");
            if(!columnName.toLowerCase().endsWith("time")
                && !columnName.toLowerCase().endsWith("date")) {
                stringBuilder.append(columnName).append(",");
            }
        }

        stringBuilder.deleteCharAt(stringBuilder.length() - 1).append(")\n" +
                "        values \n        (");

        for (Map<String, String> map : list) {
            String columnName = map.get("column_name");
            String columnType = map.get("column_type");
            String fieldName = "param." + StringUtils.getFieldName(columnName);
            String jdbcType=", jdbcType=" + StringUtils.getJdbcTypeName(columnType);
            if(!columnName.toLowerCase().endsWith("time")
                    && !columnName.toLowerCase().endsWith("date")) {
                stringBuilder.append("#{").append(fieldName).append(jdbcType).append("},");
            }
        }

        stringBuilder.deleteCharAt(stringBuilder.length() - 1).append(")\n");
        stringBuilder.append("    </insert>\n\n");
        stringBuilder.append("    <update id=\"updateByKey").append("\">\n" +
                "        update ").append(table).append("\n" +
                "        <set>\n");

        for (Map<String, String> map : list) {
            String columnName = map.get("column_name");
            String columnType = map.get("column_type");
            String jdbcType=", jdbcType=" + StringUtils.getJdbcTypeName(columnType);
            String fieldName = "param." + StringUtils.getFieldName(columnName);
            if (!keyList.contains(map)) {
                if(!columnName.toLowerCase().endsWith("time")
                        && !columnName.toLowerCase().endsWith("date")) {
                    stringBuilder.append("            <if test=\"").append(fieldName).append(" !=null and ").append(fieldName).append(" !=''\">\n                ")
                            .append(columnName).append("=#{").append(fieldName).append(jdbcType).append("},\n" +
                            "            </if>\n");
                }
            }
        }

        stringBuilder.append("        </set>\n" +
                "        where ").append(keys).append("    </update>\n\n");
        stringBuilder.append("    <delete id=\"deleteByKey\">\n" +
                "        delete from ").append(table).append(" where ").append(keys).append("    </delete>\n\n");
        stringBuilder.append("</mapper>");
        return stringBuilder.toString();
    }

    /**
     * Service文件内容
     */
    public static String getService(ParamVO paramVO) {
        String module = paramVO.getModule();
        String className = paramVO.getClassName();
        String fieldClassName = paramVO.getFieldClassName();
        String tableNameDesc = paramVO.getTableNameDesc();
        return "package " + module + ".service;\n\n" +
                "import com.baomidou.mybatisplus.extension.plugins.pagination.Page;\n" +
                "import " + module + ".vo." + className + "VO;\n" +
                "import java.util.List;\n\n" +
                "/**\n" +
                "* " + tableNameDesc + "\n" +
                "*/\n" +
                "public interface " + className + "Service {\n\n" +
                "    List<" + className + "VO> findByWhere(Page<?> page, " + className + "VO " + fieldClassName + "VO);\n\n" +
                "    " + className + "VO findByKey(" + className + "VO " + fieldClassName + "VO);\n\n" +
                "    int insert(" + className + "VO " + fieldClassName + "VO);\n\n" +
                "    int updateByKey(" + className + "VO " + fieldClassName + "VO);\n\n" +
                "    int deleteByKey(" + className + "VO " + fieldClassName + "VO);\n\n" +
                "}";
    }

    /**
     * ServiceImpl文件内容
     */
    public static String getServiceImpl(ParamVO paramVO) {
        String module = paramVO.getModule();
        String className = paramVO.getClassName();
        String fieldClassName = paramVO.getFieldClassName();
        String tableNameDesc = paramVO.getTableNameDesc();
        String toEntityString = toEntityString(paramVO);
        return "package " + module + ".service.impl;\n\n" +
                "import com.baomidou.mybatisplus.extension.plugins.pagination.Page;\n" +
                (toEntityString.contains("new BigDecimal(")? "import java.math.BigDecimal;\n":"") +
                "import org.springframework.stereotype.Service;\n" +
                "import org.springframework.beans.factory.annotation.Autowired;\n" +
                "import java.util.ArrayList;\n" +
                "import java.util.List;\n\n" +
                "import " + module + ".vo." + className + "VO;\n" +
                "import " + module + ".dao.entity." + className + "Entity;\n" +
                "import " + module + ".service." + className + "Service;\n" +
                "import " + module + ".dao." + className + "Dao;\n\n" +
                "/**\n" +
                "* " + tableNameDesc + "\n" +
                "*/\n" +
                "@Service\n" +
                "public class " + className + "ServiceImpl implements " + className + "Service {\n\n" +
                "    @Autowired\n" +
                "    private " + className + "Dao " + fieldClassName + "Dao;\n\n" +
                "    @Override\n" +
                "    public List<" + className + "VO> findByWhere(Page<?> page, " + className + "VO " + fieldClassName + "VO){\n" +
                "        List<" + className + "VO> list = new ArrayList<>();\n" +
                "        List<" + className + "Entity> list0 = " + fieldClassName + "Dao.findByWhere(page, " + fieldClassName + "VO);\n" +
                "        for (" + className + "Entity " + fieldClassName + "Entity : list0) {\n" +
                "            list.add(to" + className + "VO(" + fieldClassName + "Entity));\n" +
                "        }\n" +
                "        return list;\n" +
                "    }\n\n" +
                "    @Override\n" +
                "    public " + className + "VO findByKey(" + className + "VO " + fieldClassName + "VO){\n" +
                "        " + className + "Entity " + fieldClassName + "Entity = " + fieldClassName + "Dao.findByKey(" + fieldClassName + "VO);\n" +
                "        return to" + className + "VO(" + fieldClassName + "Entity);\n" +
                "    }\n\n" +
                "    @Override\n" +
                "    public int insert(" + className + "VO " + fieldClassName + "VO){\n" +
                "        return " + fieldClassName + "Dao.insert(to" + className + "Entity(" + fieldClassName + "VO));\n" +
                "    }\n\n" +
                "    @Override\n" +
                "    public int updateByKey(" + className + "VO " + fieldClassName + "VO){\n" +
                "        return " + fieldClassName + "Dao.updateByKey(to" + className + "Entity(" + fieldClassName + "VO));\n" +
                "    }\n\n" +
                "    @Override\n" +
                "    public int deleteByKey(" + className + "VO " + fieldClassName + "VO){\n" +
                "        return " + fieldClassName + "Dao.deleteByKey(" + fieldClassName + "VO);\n" +
                "    }\n\n" + toVOString(paramVO) + toEntityString +
                "}";
    }

    private static String toVOString(ParamVO paramVO) {
        List<Map<String, String>> list = paramVO.getList();
        String className = paramVO.getClassName();
        String fieldClassName = paramVO.getFieldClassName();
        StringBuilder stringBuilder = new StringBuilder("    private " + className + "VO to" + className + "VO(" + className + "Entity " + fieldClassName + "Entity) {\n" +
                "        " + className + "VO " + fieldClassName + "VO = new " + className + "VO();\n");
        for (Map<String, String> map : list) {
            String columnName = map.get("column_name");
            String columnType = map.get("column_type");
            String fieldName = StringUtils.getFieldName(columnName);
            String fieldTypeName = StringUtils.getFieldTypeName(columnType);
            if("Timestamp".equals(fieldTypeName) || "Date".equals(fieldTypeName)) {
                continue;
            }
            String gsField = StringUtils.getMethodName(fieldName, "");
            if("String".equals(fieldTypeName)) {
                stringBuilder.append("        ").append(fieldClassName).append("VO.set")
                        .append(gsField).append("(").append(fieldClassName).append("Entity.get")
                        .append(gsField).append("());\n");
            } else {
                stringBuilder.append("        ").append(fieldClassName).append("VO.set")
                        .append(gsField).append("(String.valueOf(").append(fieldClassName).append("Entity.get")
                        .append(gsField).append("()));\n");
            }
        }
        stringBuilder.append("        return ").append(fieldClassName).append("VO;\n    }\n\n");
        return stringBuilder.toString();
    }

    private static String toEntityString(ParamVO paramVO) {
        List<Map<String, String>> list = paramVO.getList();
        String className = paramVO.getClassName();
        String fieldClassName = paramVO.getFieldClassName();
        StringBuilder stringBuilder = new StringBuilder("    private " + className + "Entity to" + className + "Entity(" + className + "VO " + fieldClassName + "VO) {\n" +
                "        " + className + "Entity " + fieldClassName + "Entity = new " + className + "Entity();\n");
        for (Map<String, String> map : list) {
            String columnName = map.get("column_name");
            String columnType = map.get("column_type");
            String fieldName = StringUtils.getFieldName(columnName);
            String fieldTypeName = StringUtils.getFieldTypeName(columnType);
            if("Timestamp".equals(fieldTypeName) || "Date".equals(fieldTypeName)) {
                continue;
            }
            String gsField = StringUtils.getMethodName(fieldName, "");
            if("String".equals(fieldTypeName)) {
                stringBuilder.append("        ").append(fieldClassName).append("Entity.set")
                        .append(gsField).append("(").append(fieldClassName).append("VO.get")
                        .append(gsField).append("());\n");
            } else if("Integer".equals(fieldTypeName)) {
                stringBuilder.append("        String ").append(fieldName).append(" = ").append(fieldClassName).append("VO.get")
                        .append(gsField).append("();\n        if(").append(fieldName).append(" != null) {\n");
                stringBuilder.append("            ").append(fieldClassName).append("Entity.set")
                        .append(gsField).append("(Integer.parseInt(").append(fieldClassName).append("VO.get")
                        .append(gsField).append("()));\n        }\n");
            } else if("BigDecimal".equals(fieldTypeName)) {
                stringBuilder.append("        String ").append(fieldName).append(" = ").append(fieldClassName).append("VO.get")
                        .append(gsField).append("();\n        if(").append(fieldName).append(" != null) {\n");
                stringBuilder.append("            ").append(fieldClassName).append("VO.set")
                        .append(gsField).append("(new BigDecimal(").append(fieldClassName).append("Entity.get")
                        .append(gsField).append("()));\n        }\n");
            }
        }
        stringBuilder.append("        return ").append(fieldClassName).append("Entity;\n    }\n\n");;
        return stringBuilder.toString();
    }

    /**
     * Entity文件内容
     * @param paramVO paramVO
     * @param bool 是否需要swagger文档
     */
    public static String getController(ParamVO paramVO, boolean bool) {
        String module = paramVO.getModule();
        String corePackage = paramVO.getCorePackage();
        String className = paramVO.getClassName();
        String fieldClassName = paramVO.getFieldClassName();
        String tableNameDesc = paramVO.getTableNameDesc();
        return "package " + module + ".controller;\n\n" +
                "import com.baomidou.mybatisplus.extension.plugins.pagination.Page;\n" +
                (bool? "import io.swagger.v3.oas.annotations.Operation;\n" +
                "import io.swagger.v3.oas.annotations.tags.Tag;\n":"") +
                "import org.springframework.beans.factory.annotation.Autowired;\n" +
                "import org.springframework.http.MediaType;\n" +
                "import org.springframework.web.bind.annotation.*;\n" +
                "import java.util.List;\n" +
                "import java.util.HashMap;\n" +
                "import java.util.Map;\n\n" +
                "import " + module + ".vo." + className + "VO;\n" +
                "import " + module + ".service." + className + "Service;\n" +
                "import " + corePackage + ".common.base.BaseResponse;\n\n" +
                "/**\n" +
                "* " + tableNameDesc + "\n" +
                "*/\n" +
                "@RestController\n" +
                "@RequestMapping(\"/" + fieldClassName + "\")\n" +
                (bool?"@Tag(name = \"" + tableNameDesc + "\", description = \"" + tableNameDesc + "\")\n":"") +
                "public class " + className + "Controller {\n\n" +
                "    @Autowired\n" +
                "    private " + className + "Service " + fieldClassName + "Service;\n\n" +
                (bool?"    @Operation(summary = \"分页查询列表\", description = \"分页查询列表\")\n":"") +
                "    @RequestMapping(value = \"findByWhere\", method = {RequestMethod.POST}, produces = {MediaType.APPLICATION_JSON_VALUE})\n" +
                "    public BaseResponse<Map<String, Object>> findByWhere(@RequestBody " + className + "VO " + fieldClassName + "VO, Page<" + className + "VO> page){\n" +
                "        BaseResponse<Map<String, Object>> baseResponse = new BaseResponse<>();\n" +
                "        List<" + className + "VO> list = " + fieldClassName + "Service.findByWhere(page, " + fieldClassName + "VO);\n" +
                "        Map<String, Object> map = new HashMap<>();\n" +
                "        map.put(\"page\",page);\n" +
                "        map.put(\"list\",list);\n" +
                "        baseResponse.ok(map);\n" +
                "        return baseResponse;\n" +
                "    }\n\n" +
                (bool?"    @Operation(summary = \"根据id查详情\", description = \"根据id查详情\")\n":"") +
                "    @RequestMapping(value = \"findByKey\", method = {RequestMethod.POST}, produces = {MediaType.APPLICATION_JSON_VALUE })\n" +
                "    public BaseResponse<" + className + "VO> findByKey(@RequestBody " + className + "VO " + fieldClassName + "VO){\n" +
                "        BaseResponse<" + className + "VO> baseResponse = new BaseResponse<>();\n" +
                "        " + className + "VO " + fieldClassName + "VO1 = " + fieldClassName + "Service.findByKey(" + fieldClassName + "VO);\n" +
                "        if(" + fieldClassName + "VO1 == null){\n" +
                "            baseResponse.errMsg(\"数据为空\");\n" +
                "        }else{\n" +
                "            baseResponse.ok(" + fieldClassName + "VO1);\n" +
                "        }\n" +
                "        return baseResponse;\n" +
                "    }\n\n" +
                (bool?"    @Operation(summary = \"添加一条记录\", description = \"添加一条记录\")\n":"") +
                "    @RequestMapping(value = \"insert" + className + "\", method = {RequestMethod.POST}, produces = {MediaType.APPLICATION_JSON_VALUE })\n" +
                "    public BaseResponse<Object> insert" + className + "(@RequestBody " + className + "VO " + fieldClassName + "VO){\n" +
                "        BaseResponse<Object> baseResponse = new BaseResponse<>();\n" +
                "        int count = " + fieldClassName + "Service.insert(" + fieldClassName + "VO);\n" +
                "        if(count > 0){\n" +
                "            baseResponse.ok();\n" +
                "        }else{\n" +
                "            baseResponse.errMsg(\"新增数据失败\");\n" +
                "        }\n" +
                "        return baseResponse;\n" +
                "    }\n\n" +
                (bool?"    @Operation(summary = \"修改一条记录\", description = \"修改一条记录\")\n":"") +
                "    @RequestMapping(value = \"update" + className + "ByKey\", method = {RequestMethod.POST}, produces = {MediaType.APPLICATION_JSON_VALUE })\n" +
                "    public BaseResponse<Object> update" + className + "ByKey(@RequestBody " + className + "VO " + fieldClassName + "VO){\n" +
                "        BaseResponse<Object> baseResponse = new BaseResponse<>();\n" +
                "        int count = " + fieldClassName + "Service.updateByKey(" + fieldClassName + "VO);\n" +
                "        if(count > 0){\n" +
                "            baseResponse.ok();\n" +
                "        }else{\n" +
                "            baseResponse.errMsg(\"修改数据失败\");\n" +
                "        }\n" +
                "        return baseResponse;\n" +
                "    }\n\n" +
                (bool?"    @Operation(summary = \"删除一条记录\", description = \"删除一条记录\")\n":"") +
                "    @RequestMapping(value = \"deleteByKey\", method = {RequestMethod.POST}, produces = {MediaType.APPLICATION_JSON_VALUE })\n" +
                "    public BaseResponse<Object> deleteByKey(@RequestBody " + className + "VO " + fieldClassName + "VO){\n" +
                "        BaseResponse<Object> baseResponse = new BaseResponse<>();\n" +
                "        int count = " + fieldClassName + "Service.deleteByKey(" + fieldClassName + "VO);\n" +
                "        if(count > 0){\n" +
                "            baseResponse.ok();\n" +
                "        }else{\n" +
                "            baseResponse.errMsg(\"删除数据失败\");\n" +
                "        }\n" +
                "        return baseResponse;\n" +
                "    }\n\n" +
                "}";
    }

    private static String getTableEngName(String tableName) {
        String table = tableName;
        if(tableName.contains("-")) {
            table = tableName.substring(0, tableName.indexOf("-"));
        }
        return table;
    }
}
